跳到主要内容

harbor ci-cd

CI流水线中制品库集成

镜像规范

业务/服务:commitId

镜像上传

docker login 192.168.1.200:8088
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

docker tag nginx:1.9.1 192.168.1.200:8088/devops03/devops03-maven-service:1.9.1
docker push 192.168.1.200:8088/devops03/devops03-maven-service:1.9.1

镜像下载

docker pull 192.168.1.200:8088/devops03/devops03-maven-service:1.9.1

CI流水线集成

💘 实践:harbor CI流水线中制品库集成(测试成功)-2022.6.25

1.Jenkins

pipeline {
agent {
label "build"
}

stages {
stage("DockerBuild"){
steps{
script{
imageName = "${env.buName}/${env.serviceName}"
imageTag = "${env.branchName}-${env.commitID}"
sh """
#登录镜像仓库
docker login -u admin -p Harbor12345 192.168.1.200:8088

# 构建镜像
docker build -t 192.168.1.200:8088/${imageName}:${imageTag} .

# 上传镜像
docker push 192.168.1.200:8088/${imageName}:${imageTag}

# 删除镜像
sleep 2
docker rmi 192.168.1.200:8088/${imageName}:${imageTag}
"""
}
}
}
}
}
}
  • 我们先手动上传下镜像到harbor里:

自己的构建机器要配置下这个:

image-20220625093812765

image-20220622195053609

  • 来到devops4-maven-service项目,创建一个dockerfile:

image-20220622125010468

  • 先给它加进去看下效果:

来到devops4-maven-service,给它创建一个Dockerfile文件:

image-20220622204230686

再将本次代码拷贝到共享库里,看下效果:

image-20220625093948367

  • 构建并观察效果

image-20220625094016308

image-20220625094056616

符合预期。😘

2.GitLabCI

.dockerbuild:
tags:
- "${RUNNER_TAG}"
stage: dockerbuild
rules:
- if: '$RUN_TYPE == "CI"'
when: always
- when: never
script:
|-
imageName=${CI_PROJECT_ROOT_NAMESPACE}/${CI_PROJECT_NAME}:${CI_COMMIT_BRANCH}-${CI_COMMIT_SHORT_SHA}
#登录镜像仓库
docker login -u admin -p Harbor12345 192.168.1.200:8088
# 构建镜像
docker build -t 192.168.1.200:8088/${imageName} .
# 上传镜像
docker push 192.168.1.200:8088/${imageName}
# 删除镜像
sleep 2
docker rmi 192.168.1.200:8088/${imageName}

📍 自己测试过程:

  • 配置代码:

我这里为啥报了这个错误呢?

串行和并行都测试过了的啊:

image-20220622223135142

估计是自己的gitlab-runner用户权限不对,这里在上面配置上sudo:

image-20220622223239055

再次尝试就可以了。。

记得上次老师没做过这个配置啊……

  • 并行测试:

image-20220625095136020

image-20220625095115653

奇怪啊,老师,当时记得是并行测试时有问题的……

image-20220622224015158

  • 串行测试:

image-20220625094806647

image-20220622223051587

image-20220622223113240

image-20220625094710138

image-20220625094722925

注意:因为前面jenkins那里已经上传了一个相同镜像,所以这里只显示为一个;

image-20220625094732707

符合预期。😘

🍀 问题

  • 问题现象

之前老版本harbor测试,都没报这个错误来着的;

新版本测试,为啥报这个错误了呢?

jenkins上都可以正常推送上去,但是gitlab-CI就有问题了;

image-20220624083013179

image-20220624082349516

We trust you have received the usual lecture from the local System

18Administrator. It usually boils down to these three things:

19 #1) Respect the privacy of others.

20 #2) Think before you type.

21 #3) With great power comes great responsibility.

22sudo: no tty present and no askpass program specified

image-20220624083222447

  • 这里测试都是可以使用sudo命令的啊……

image-20220624082625679

  • 最后发现,串行测试没问题,但是并行测试一直报这个错误……奇怪

Harbor REST API

http://192.168.1.200:8088/devcenter-api-2.0

image-20220622224741601

Harbor API 实践【New】

💘 实践:Harbor API 实践(批量删除docker镜像)-2022.6.25

在Harbor中批量的创建一些标签

image-20220622224924231

创建一个Jenkins作业, 不需要配置任何参数。 只需要把Jenkinfile内容放进去。

image-20220622224942117

jenkinsfile内容:

  • 通过API 获取所有的tag标签列表。
  • 将标签信息用INPUT交互式的展示。
  • 调用删除接口,删除镜像标签。

image-20220622225008544

import groovy.json.JsonSlurper

/*
清理docker镜像

1. 获取镜像列表
2. 用户选择删除
3. 调用api删除

*/
pipeline {
agent {
label "build"
}

stages{

stage("GetTags"){
steps{
script{
env.projectName = "acmp"
env.repoName = "acmp-nginx-service"
env.result = GetArtifactTag(env.projectName, env.repoName)
env.result = env.result - '[' - ']'
}
}
}

stage("Clean"){
steps{
script{

def result = input message: "是否删除${env.projectName}项目的${env.repoName}这些标签:",
parameters: [extendedChoice(defaultValue: "${env.result}",
multiSelectDelimiter: ',',
name: 'taga',
quoteValue: false,
saveJSONParameterToFile: false,
type: 'PT_CHECKBOX',
value: "${env.result}",
visibleItemCount: 20)]
println("${result}")
// println("Delete ${taga}, doing.......")
// tags = "${taga}" - '[' - ']'

for(t in result.split(',')){
println("Delete >>>>" + t.trim())
DeleteArtifactTag(env.projectName,env.repoName, t.trim())
}
}
}

}
}
}


// 删除镜像tag
def DeleteArtifactTag(projectName,repoName, tagName){
harborAPI = "http://192.168.1.200:8088/api/v2.0/projects/${projectName}/repositories/${repoName}"
apiURL = "artifacts/${tagName}/tags/${tagName}"
sh """ curl -X DELETE "${harborAPI}/${apiURL}" -H "accept: application/json" -u admin:Harbor12345 """
}

// 获取镜像的所有标签
// acmp-nginx-service
def GetArtifactTag(projectName,repoName ){
harborAPI = "http://192.168.1.200:8088/api/v2.0/projects/${projectName}/repositories/${repoName}"
apiURL = "artifacts?page=1&page_size=10"
response = sh returnStdout: true, script: """curl -X GET "${harborAPI}/${apiURL}" -H "accept: application/json" -u admin:Harbor12345 """
response = readJSON text: """${response - "\n"}"""
tags = []
for (t in response[0].tags){
tags << t.name
}

return tags
}

最终效果:【Harbor镜像已经清空了】

image-20220622225105218

📍 自己测试过程:

  • 来到devops4-maven-service仓库,创建一个新分支:

image-20220622225247292

然后在jenkins里跑一次流水线:

image-20220622225353117

image-20220625095502517

相同的镜像,harbor就自动给你归类了:

  • 这里在做一个小小的改动:

image-20220622225554432

image-20220622225621449

image-20220625095611789

  • 创建一个jeninks job:

devops4-clean-harbor

image-20220623141411891

image-20220623141351548

image-20220623141402534

  • 安装插件

image-20220625100829901

  • 开始构建:

image-20220625095746943

点击这个Input requested:

image-20220625095816020

image-20220625095837790

老师这里当时好像也是只选择了一个镜像,次问题暂且搁置吧……🤣

image-20220625095921089

这里只是把tag给去掉了:

image-20220625095951183

但是,再跑一次的话就会报错……

image-20220625100035069

实验结束。

本次完整代码如下:

import groovy.json.JsonSlurper

/*
清理docker镜像

1. 获取镜像列表
2. 用户选择删除
3. 调用api删除

*/
pipeline {
agent {
label "build"
}

stages{

stage("GetTags"){
steps{
script{
env.projectName = "${env.repoName}".split("-")[0]
env.result = GetArtifactTag(env.projectName, env.repoName)
env.result = env.result - '[' - ']'
}
}
}

stage("Clean"){
steps{
script{

def result = input message: "是否删除${env.projectName}项目的${env.repoName}这些标签:",
parameters: [extendedChoice(defaultValue: "${env.result}",
multiSelectDelimiter: ',',
name: 'taga',
quoteValue: false,
saveJSONParameterToFile: false,
type: 'PT_CHECKBOX',
value: "${env.result}",
visibleItemCount: 20)]
println("${result}")
// println("Delete ${taga}, doing.......")
// tags = "${taga}" - '[' - ']'

for(t in result.split(',')){
println("Delete >>>>" + t.trim())
DeleteArtifactTag(env.projectName,env.repoName, t.trim())
}
}
}

}
}
}


// 删除镜像tag
def DeleteArtifactTag(projectName,repoName, tagName){
harborAPI = "http://172.29.9.103:8088/api/v2.0/projects/${projectName}/repositories/${repoName}"
apiURL = "artifacts/${tagName}/tags/${tagName}"
sh """ curl -X DELETE "${harborAPI}/${apiURL}" -H "accept: application/json" -u admin:Harbor12345 """
}

// 获取镜像的所有标签
// acmp-nginx-service
def GetArtifactTag(projectName,repoName ){
harborAPI = "http://172.29.9.103:8088/api/v2.0/projects/${projectName}/repositories/${repoName}"
apiURL = "artifacts?page=1&page_size=10"
response = sh returnStdout: true, script: """curl -X GET "${harborAPI}/${apiURL}" -H "accept: application/json" -u admin:Harbor12345 """
response = readJSON text: """${response - "\n"}"""
tags = []
for (t in response[0].tags){
tags << t.name
}

return tags
}

注意:harbor是自带镜像删除策略的

image-20220623082730430

image-20220625100917874